import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/*
    读写锁的实现
    ps:如果先执行读操作那么读取的数据为null，这是正常现象。要数据写入之后再读取才可以读到数据，实际项目中可以开启另一个线程循环判断获取到的值是否为空，再重新尝试获取值。
 */
public class ReadWriteLock {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();

        for (int i = 0; i < 5; i++) {
            final int NUM = i;
            new Thread(()->{
                myCache.put_k_v(NUM+"",NUM+"");
            },String.valueOf(i)).start();
        }

        for (int i = 0; i < 5; i++) {
            final int NUM = i;
            new Thread(()->{
                myCache.get_k(NUM+"");
            },String.valueOf(i)).start();
        }
    }
}

/*
    缓存模拟
 */
class MyCache{
    private final Map<String,Object> map = new HashMap<>();
    private final ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();

    public void put_k_v(String key, Object val){
        reentrantReadWriteLock.writeLock().lock();
        try{
            System.out.println(key +"\t开始写入数据");
            //模拟网络拥堵情况
            TimeUnit.MILLISECONDS.sleep(300);
            map.put(key,val);
            System.out.println(key +"\t写入完成");
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            reentrantReadWriteLock.writeLock().unlock();
        }
    }

    public void get_k(String key){
        reentrantReadWriteLock.readLock().lock();
        try{
            System.out.println(key +"\t开始读取数据");
            TimeUnit.MILLISECONDS.sleep(300);
            Object result = map.get(key);
            System.out.println(key +"\t数据读取成功："+result);
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            reentrantReadWriteLock.readLock().unlock();
        }
    }
}
